/**
* Gumby SkipLink
*/
!function($) {

	'use strict';

	function SkipLink($el) {

		Gumby.debug('Initializing Skiplink', $el);

		this.$el = $el;
		this.targetPos = 0;
		this.duration = 0;
		this.offset = false;
		this.easing = '';
		this.update = false;

		// set up module based on attributes
		this.setup();

		var scope = this;

		// skip to target element on click or trigger of gumby.skipTo event
		this.$el.on(Gumby.click+' gumby.skip', function(e) {
			e.preventDefault();

			if(e.namespace === 'skip') {
				Gumby.debug('Skip event triggered', scope.$el);
			}

			// calculate target on each click if update var set to true
			if(scope.update) {
				scope.calculateTarget(scope.skipTo);

			// skip straight to target
			} else {
				scope.skipTo();
			}
		}).on('gumby.initialize', function() {
			Gumby.debug('Re-initializing Skiplink', scope.$el);
			scope.setup();
		});
	}

	// set up module based on attributes
	SkipLink.prototype.setup = function() {
		this.duration = Number(Gumby.selectAttr.apply(this.$el, ['duration'])) || 200;
		this.offset = Gumby.selectAttr.apply(this.$el, ['offset']) || false;
		this.easing = Gumby.selectAttr.apply(this.$el, ['easing']) || 'swing';
		this.update = Gumby.selectAttr.apply(this.$el, ['update']) ? true : false;

		this.calculateTarget();
	};

	// calculate target px point to skip to
	SkipLink.prototype.calculateTarget = function(cb) {

		var scope = this,
			target = Gumby.selectAttr.apply(this.$el, ['goto']),
			$target;

		// 'top' specified so target is 0px
		if(target == 'top') {
			this.targetPos = 0;

		// px point specified
		} else if($.isNumeric(target)) {
			this.targetPos = Number(target);
		} else {

			// check for element with target as selector
			$target = $(target);

			// target does not exist, we need a target
			if(!$target.length) {
				Gumby.error('Cannot find skiplink target: '+target);
				return false;
			}

			this.targetPos = $target.offset().top;
		}

		if(cb) {
			cb.apply(this);
		}
	};

	// animate body, html scrollTop value to target px point
	SkipLink.prototype.skipTo = function() {
		
		Gumby.debug('Skipping to target', this.$el);

		var scope = this;

		// slide to position of target
		$('html,body').animate({
			'scrollTop' : this.calculateOffset()
		}, this.duration, this.easing).promise().done(function() {

			Gumby.debug('Triggering onComplete event', scope.$el);
			scope.$el.trigger('gumby.onComplete');
		});
	};

	// calculate offset with current target point
	SkipLink.prototype.calculateOffset = function() {
		// no offset so return target here
		if(!this.offset) {
			return this.targetPos;
		}

		// negative / positive
		var op = this.offset.substr(0, 1),
			off = Number(this.offset.substr(1, this.offset.length));

		// subtract offset from target position
		if(op === '-') {
			return this.targetPos - off;
		// add offset to target position
		} else if(op === '+') {
			return this.targetPos + off;
		}
	};

	// add initialisation
	Gumby.addInitalisation('skiplink', function(all) {
		$('.skiplink > a, .skip').each(function() {
			var $this = $(this);

			// this element has already been initialized
			// and we're only initializing new modules
			if($this.data('isSkipLink') && !all) {
				return true;

			// this element has already been initialized
			// and we need to reinitialize it
			} else if($this.data('isSkipLink') && all) {
				$this.trigger('gumby.initialize');
				return true;
			}

			// mark element as initialized
			$this.data('isSkipLink', true);
			new SkipLink($this);
		});
	});

	// register UI module
	Gumby.UIModule({
		module: 'skiplink',
		events: ['initialize', 'onComplete', 'skip'],
		init: function() {
			Gumby.initialize('skiplink');
		}
	});
}(jQuery);
